import axios from "axios"
import type {TTSChannel, VoiceModel} from "~/utils/jiangying";
import {blobtoFile, ImageUrlToBlob, useUtilsUploadFileToOSS} from "~/utils/FileUtils";


/**
 * 语音合成
 * @param params
 * @param options
 */
export const useVoiceTTS = async (params: TTSParams, options?: TTSOptions): Promise<string | undefined> => {
    const {useOss} = storeToRefs(useStableDiffusionStore())
    if (options?.useVits && options.useLocalVits) {
        const audiofile= await _useVocieVitsTextToSpeech(params, options)
        const output = await useUtilsUploadFileToOSS(audiofile, 'audio')
        if (output && useOss.value) return  output
        if(!useOss) return URL.createObjectURL(audiofile)
    } else if(options?.useChattts && options.useLocalChattts) {
        const audiofile= await _useVoiceChatTTS(params, options)
        if(audiofile){
            const output = await useUtilsUploadFileToOSS(audiofile, 'audio')
            if (output && useOss.value) return  output
            if(!useOss) return URL.createObjectURL(audiofile)
        }
    }else {
        //使用服务器合成
        return await Client_POST('/tts',{params,options}) as string
    }
}

/**
 * 将文本转换为语音
 * @param param
 * @param options
 */
const _useVocieVitsTextToSpeech = async (param: TTSParams, options?: TTSOptions): Promise<File> => {
    //如果没有任何声音模型提示
    const {voiceModels, localVitsUrl} = useWorkEditStore()
    const data = {
        text: param.text,
        character: param.character || voiceModels[0].name,
    }
    const {data: res} = await axios({
        method: "POST",
        url: `${options?.useLocalVits ? localVitsUrl : useRuntimeConfig().public.baseVitsurl}/tts`,
        responseType: "arraybuffer",
        data
    })
    // 将 ArrayBuffer 数据写入文件
    return _useFileArrayBufferToWavFile(res, `tts_${param.character}_${param.text}.wav`)
}
const _useVoiceChatTTS = async (params: TTSParams, options?: TTSOptions): Promise<File | undefined> => {
    //如果没有任何声音模型提示
    const {voiceModels, localChatttsUrl} = useWorkEditStore()
    const data = {
        text: params.text,
        voice: params.voice || "2",
        temperature: params.temperature || 0.3,
        top_p: params.top_p || 0.7,
        top_k: params.top_k || 20,
        refine_max_new_token: '384',
        infer_max_new_token: '2048',
        skip_refine: 0,
        is_split: 1,
        custom_voice: params.custom_voice || 0
    } as TTSParams
    //将data转换为formdata
    const dataForm = axios.toFormData(data)
    const url=`${options?.useLocalChattts ? localChatttsUrl : useRuntimeConfig().public.baseChatttsurl}/tts`
    const {data: {code, audio_files}} = await axios.postForm(url, dataForm)
    if (code === 0) {
        const url = audio_files[0].url as string
        const blob = await ImageUrlToBlob(url)
        return await blobtoFile(blob, audio_files.filename)
    }
}
/**
 * 获取本地支持的语音人物和情感,返回格式：
 * {"Hutao": ["default"],"八重神子": ["default"]}
 *
 */
export const useVoiceVitsGetCharacters = async (): Promise<VoiceModel[]> => {
    const {localVitsUrl,useLocalVits} = useWorkEditStore()
    if(useLocalVits){
        const {data} = await axios({
            method: "GET",
            url: `${localVitsUrl}/character_list`,
        })
        //将data转换为VoiceModels
        const voiceModels = [] as VoiceModel[]
        Object.keys(data).forEach((key, index) => {
            const voiceModel = {
                id: index,
                name: key,
                emotions: data[key]
            }
            voiceModels.push(<VoiceModel>voiceModel)
        })
        console.log('获取系统支持的语音模型及情感列表', voiceModels)
        return voiceModels
    }else {
        return await Client_GET('/tts/character_list') as VoiceModel[]
    }

}
/**
 * 上传到服务器，或者转换为URL
 */
export const useVoiceVitsUpload = async (file: File): Promise<string | undefined> => {
    //如果启动了OSS
    const {useOss} = useStableDiffusionStore()
    if (useOss) {
        return await useUtilsUploadFileToOSS(file, 'audio')
    } else {
        return URL.createObjectURL(file)
    }
}

/**
 * 将ArrayBuffer转换为WAV格式的File对象
 * @param buffer
 * @param filename
 * @returns
 */
const _useFileArrayBufferToWavFile = (buffer: ArrayBuffer, filename: string) => {
    // 假设这是一个WAV格式的ArrayBuffer
    // 这里需要确保buffer是一个WAV格式的ArrayBuffer
    // 创建Blob对象
    const wavBlob = new Blob([buffer], {type: 'audio/wav'});
    // saveAs(wavBlob, filename);
    // 创建File对象
    return new File([wavBlob], filename, {
        type: 'audio/wav',
    });
}

//TTS参数接口
export interface TTSParams extends TTSOptionalParams{
    //GPTVITS
    text: string;
}


export interface TTSOptionalParams{
    character?: string;
    //ChatTTS
    prompt?: string,
    voice?: string,
    temperature?: number,
    top_p?: number,
    top_k?: number,
    refine_max_new_token?: string,
    infer_max_new_token?: string,
    skip_refine?: 0 | 1,
    is_split?: 0 | 1,
    custom_voice?: number
}

//TTS Options
export interface TTSOptions {
    useVits?: boolean;
    useLocalVits?: boolean;
    useChattts?: boolean;
    useLocalChattts?: boolean;
    ttsChannel?:TTSChannel;
    url?:string;
}